package com.hzit.portal.service.impl;

import com.alibaba.fastjson.JSON;
import com.fasterxml.jackson.databind.util.ByteBufferBackedInputStream;
import com.hzit.portal.config.MyKeyGenerator;
import com.hzit.portal.service.PortalService;
import com.ruoyi.common.core.constant.Constants;
import com.ruoyi.common.core.constant.PortalConstants;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.system.api.RemoteManagerService;
import com.ruoyi.system.api.domain.Content;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.swing.text.html.parser.ContentModel;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

import static com.ruoyi.common.core.constant.PortalConstants.CONTENT_LIST_PREFIX;

/**
 * 类名：
 * 作者：WF
 * 功能：
 */
@Service
public class PortalServiceImpl implements PortalService {
	@Autowired
	private RemoteManagerService managerService;
	@Autowired
	private StringRedisTemplate redisTemplate;

	//1. 根据广告id查询广告列表 (老版本做法)
	@Override
	public List<Content> findById(Long id) {
		List<Content> contentList = null;
		//1.1 从redis中查询数据（轮播图广告数据）
		String contents = (String) redisTemplate.opsForHash().get(CONTENT_LIST_PREFIX, id + "");
		//1.2 如果存在数据，就转换为List<Content>
		if(StringUtils.isNotBlank(contents)){
			//从redis中取得数据
			contentList = JSON.parseArray(contents,Content.class);
		}else{
			System.out.println("从远程数据库中查询。。。");
			R<List<Content>> r = managerService.findById(id);
			contentList = r.getData();
			//再将其放到redis中
			redisTemplate.opsForHash().put(CONTENT_LIST_PREFIX,id + "",JSON.toJSONString(contentList));
		}
		//1.3 最后返回
		return contentList;
	}

	//2. 利用缓存框架SpringCache完成缓存操作
	//@Cacheable: 代表首从redis中得到集合数据，如果得不到才访问数据库从数据库中获取
	// 如果缓存中没有数据才访问此方法，否则，不调用方法从缓存中直接取数据！
	@Override
	// @Cacheable(key = "#root.methodName",value = "contents")
	//keyGenerator：定制主键生成器，实现KeyGenerator接口
	@Cacheable(keyGenerator="myKeyGenerator",value = "contents")
	public List<Content> findById2(Long id) {
		System.out.println("正在从远程数据库采取数据。。。");
		R<List<Content>> r = managerService.findById(id);
		return r.getData();
	}

	// 根据广告id查询广告
	// @CachePut: 每次执行都会调用方法，不管redis中否有此数据！
	@Override
	@CachePut(key="'findOne'",value = "content")
	public Content findOne(Long id) {
		System.out.println("根据广告id查询广告。。。");
		R<Content> r = managerService.findContentById(id);
		return r.getData();
	}
	// 添加广告
	//@CacheEvict：删除指定缓存，可以根据key和value进行删除指定的缓存
	//也可使用allEntries参数来删除指定value的所有名称空间下的缓存（相同的value下的不同的key都可以删除）
	@Override
	// @CacheEvict(key="'findById2'",value = "contents")
	@CacheEvict(allEntries = true,value = "contents")
	// @Caching(): 主要用于组合多个操作
	public R add(Content content) {
		return managerService.insert(content);
	}

	//1. 根据分类id查询广告列表
	//放redis的说明：
	//① 大key：hzit_contents：分类id
	//② 小key：广告商品的id
	//③ 值：某件商品
	public List<Content> findById3(Long id) {
		//1.1 从redis中得到查询的数据
		HashOperations<String, String, String> hashOperations = redisTemplate.opsForHash();
		List<String> values = hashOperations.values(CONTENT_LIST_PREFIX + id);
		List<Content> contentList = values.stream().map(m -> JSON.parseObject(m, Content.class)).collect(Collectors.toList());
		//1.2 如果数据为null
		if(Objects.isNull(contentList) || contentList.size() == 0) {
			System.out.println("正在从数据库中查询.");
			R<List<Content>> r = managerService.findById(id);
			contentList = r.getData();
			//重新放到redis
			for (Content content : contentList) {
				hashOperations.put(CONTENT_LIST_PREFIX + id,content.getId() + "",JSON.toJSONString(content));
			}
		}

		return contentList;
	}

}
